import { Vec2 } from "cc";

export class PathNode{
	    public pos:Vec2;
	    public links:number[];
	    public gCost:number;
	    public hCost:number;
	    public parent:PathNode;
		public polygonUniqueId:number;
	
	    public constructor(pos:Vec2, polygonUniqueId?:number)
	    {
	        this.pos = pos;
	        this.links = [];
	        this.gCost = 1;
	        this.hCost = 0;
	        this.parent = null;
			this.polygonUniqueId = polygonUniqueId;
	    }
	
	    public get fCost():number
	    {
	        return this.gCost + this.hCost;
	    }
	
	
	    public CompareTo ( other:PathNode):number
	    {
	        let value = this.fCost - other.fCost;
	        if(0 == value)
	        {
	            value = this.hCost - other.hCost;
	        }
	        return -value;
	    }
	}
	
	export class PolygonNavAStar {
	    public static GetPath(startNode:PathNode, endNode:PathNode, allNodes:PathNode[], pathList:Vec2[]):Vec2[]
	    {
	        let openList:PathNode[] = [];
	        let closedList:PathNode[] = [];
	        let success = false;
	        openList.push(startNode);
	        while (openList.length > 0)
	        {
	            let currentNode:PathNode = openList[0];
	            let nodeIndex = 0;
	            for (let i = 1; i < openList.length; i++)
	            {
	                if (openList[i].fCost < currentNode.fCost || (openList[i].fCost == currentNode.fCost && openList[i].hCost < currentNode.hCost))
	                {
	                    currentNode = openList[i];
	                    nodeIndex = i;
	                }
	            }
	            openList.splice(nodeIndex, 1)
	            if (currentNode == endNode){
	                success = true;
	                break;
	            }
	
	            closedList.push(currentNode);
	
	            let linkIndeces = currentNode.links;
	            for (let i = 0; i < linkIndeces.length; i++){
	                let neighbour = allNodes[ linkIndeces[i] ];
	
	                if (closedList.indexOf(neighbour) != -1){
	                    continue;
	                }
	
	                let costToNeighbour = currentNode.gCost + this.GetDistance( currentNode, neighbour );
	                if (costToNeighbour < neighbour.gCost || openList.indexOf(neighbour) == -1 ){
	
	                    neighbour.gCost = costToNeighbour;
	                    neighbour.hCost = this.GetDistance(neighbour, endNode);
	                    neighbour.parent = currentNode;
	
	                    if (openList.indexOf(neighbour) == -1){
	                        openList.push(neighbour);
	                    }
	                }
	            }
	        }
	
	        if (success)
	        {
	            let currentNode = endNode;
	            while(currentNode != startNode){
	                pathList.push(new Vec2(currentNode.pos));
	                currentNode = currentNode.parent;
	            }
	            pathList.push(new Vec2(startNode.pos));
	            pathList.reverse();
	            return pathList;
	        }
	        return null;
	    }
	
	    private static GetDistance(a:PathNode, b:PathNode):number{
	        return Vec2.distance(a.pos, b.pos);
	    }
	}
	